Skip to content

feat(batch): batch watch — live read-only view of a running shift - #576

Merged
Jammy2211 merged 1 commit into
mainfrom
feature/batch-watch-live-view
Nov 4, 2026
Merged

Jammy2211 merged 1 commit into
mainfrom
feature/batch-watch-live-view

Conversation

@Jammy2211

Copy link
Copy Markdown
Contributor

Summary

Adds pyauto-brain batch watch, a live terminal view of a running shift. Until now the shift watcher said nothing until the digest at review-at:. This view shows time left, each task's state with its pick reason, PR and CI health, the budgets, and the last ticks, redrawn in place. It is a follow-up from the orchestrator pilot (#574), wanted before the first live shift.

Closes #575

API Changes

Adds the watch verb to pyauto-brain batch, with --once and --interval (minimum 30 s); it reuses --record and --home. Adds _digest.task_state; _line now calls it and the digest's output is unchanged. Adds a new module, _watch.py.

Details
  • _digest.task_state(task, counters, health, *, live=False, lease=None, agents=None) returns (state, tier_follows). With live=True it adds the states only a held lease shows: running (agent …), blocked on a person since …, running? (… not listed — inside the grace …), and crashed — awaiting re-dispatch.
  • _watch.snapshot / render / watch / CachedHealth.
  • The budgets show live workers against max-workers: and sessions against max-sessions: separately (they are different caps; defaults come from _brief.cap_of).

Read-only and network surface

  • No write to the slot, Mind or GitHub, and no lock. A test asserts the tree is byte-identical after --once, and that looking at an unstarted shift never creates its slot.
  • Reads: one claude agents --json per refresh, only on a live shift with real worker leases; gh pr checks only for unmerged PRs, cached per interval. Both are reads the watcher already makes.

Witness

The --once view of the real shadow slot 2026-11-05-am, mid-shift:

Shift 2026-11-05-am — SHADOW · 1h 43m left
  2026-11-04T13:30Z → 2026-11-04T15:30Z   (as of 2026-11-04T13:46:22Z)
  brief: /home/jammy/Code/PyAutoLabs/organs/PyAutoMind/batches/2026-11-05-am.md

Tasks
- batch_slice — proposed (shadow) — notify — why: scoped tier notify
- board_without_gh_phase2_legs — proposed (shadow) — notify — why: scoped tier notify
- data_loading_and_selection_cuts_skill — proposed (shadow) — notify — why: scoped tier notify
- demo_subplot_ellipse_errors — proposed (shadow) — notify — why: scoped tier notify
- markdown_regeneration_sigma_min — proposed (shadow) — notify — why: scoped tier notify
- rtd_organism_currency — proposed (shadow) — notify — why: scoped tier notify

Budgets
- workers: 0 live of 2
- sessions: 0 of 6
- tokens: 0 of 0
- merges: 0 of 0 (0 unattended)
- workers crashed: 0

Last ticks
  13:31Z shadow — proposed 0, spawned 0, reaped 0, refused 0
  13:34Z shadow — proposed 0, spawned 0, reaped 0, refused 0
  13:37Z shadow — proposed 0, spawned 0, reaped 0, refused 0
  13:40Z shadow — proposed 0, spawned 0, reaped 0, refused 0
  13:43Z shadow — proposed 0, spawned 0, reaped 0, refused 0

The live fixture (tests/test_batch_watch.py):

Shift 2026-11-04-am — LIVE · 1h 30m left
  2026-11-04T09:00Z → 2026-11-04T11:00Z   (as of 2026-11-04T09:30:00Z)
  brief: /tmp/tmpxnvaxzfz/2026-11-04-am.md

Tasks
- named — not started — glance — why: named in the brief
- running — running (agent a1, working, since 2026-11-04T09:05:00Z) — glance — why: scoped tier glance — re-dispatched 1×
- blocked — blocked on a person since 2026-11-04T09:20:00Z — glance — why: scoped tier glance
- pr_open — https://github.com/example-org/example-repo/pull/11 — RUNNING — notify — why: scoped tier notify
- closing — https://github.com/example-org/example-repo/pull/12 — close-out running — glance — why: scoped tier glance
- merged — https://github.com/example-org/example-repo/pull/13 — merged unattended (close-out, opus) — glance — why: scoped tier glance
- parked — parked: awaiting-input (blocked on a person) — glance — why: scoped tier glance
- crashed — crashed — awaiting re-dispatch — glance — why: scoped tier glance

Budgets
- workers: 2 live of 3
- sessions: 4 of 6
- tokens: 1234 of 5000
- merges: 1 of 2 (1 unattended)
- workers crashed: 1

Last ticks
  09:15Z dispatch — proposed 0, spawned 1, reaped 0, refused 0
  09:18Z dispatch — proposed 0, spawned 1, reaped 0, refused 0
  09:21Z dispatch — proposed 0, spawned 1, reaped 0, refused 0
  09:24Z dispatch — proposed 0, spawned 1, reaped 0, refused 0
  09:27Z dispatch — proposed 0, spawned 1, reaped 0, refused 0

Tests

  • tests/test_batch_watch.py: 8 new tests covering live, shadow, no-tick and closed/STOP snapshots, byte-identical read-only, CLI --once, digest/watch wording parity, and the interval floor plus cached health.
  • The existing digest, shadow and close-out tests pass unchanged (the digest wording is the same).
  • Full Brain suite: 1548 passed, 1 skipped. Tenant firewall: OK.
  • Heart YELLOW, acknowledged by the human at ship.

Tier: glance — merge mode: auto-merge on green with Witness PASS, post-merge summary.

🤖 Generated with Claude Code

Adds `pyauto-brain batch watch --record <brief> [--once] [--interval N]`:
time left, each task's state, pick reason, PR and CI health, budgets and
the last ticks, redrawn in place. It writes nothing; its reads are the
watcher's own. Task wording is shared with the digest via
_digest.task_state, so the two never disagree.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Jammy2211
Jammy2211 merged commit 28fb917 into main Nov 4, 2026
2 checks passed
@Jammy2211
Jammy2211 deleted the feature/batch-watch-live-view branch November 4, 2026 13:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: batch watch — live terminal view of a running shift

1 participant